注册门面
简介
这一章,我们说一下 Laravel 引导程序之门面的注册,其实质是:执行 Illuminate\Foundation\Bootstrap\RegisterFacades 类中的 bootstrap 方法。

bootstrap 方法
不废话,直接贴 RegisterFacades 类的 bootstrap 方法
public function bootstrap(Application $app)
{
Facade::clearResolvedInstances();
Facade::setFacadeApplication($app);
AliasLoader::getInstance(array_merge(
$app->make('config')->get('app.aliases', []),
$app->make(PackageManifest::class)->aliases()
))->register();
}
首先,这段代码:
Facade::clearResolvedInstances();指,清理所有门面公共父类
Illuminate\Support\Facades\Facade保存的实例缓存。其本质,我们看这段代码
public static function clearResolvedInstances()
{
static::$resolvedInstance = [];
}明白了吧,就是将静态属性
$resolvedInstance赋值为空数组,即为清空实例缓存其次,这段代码:
Facade::setFacadeApplication($app);,门面注册的核心呀。。。我记得刚刚接触 Laravel 的时候,想使用 Redis,官方文档说,用
Illuminate\Support\Facades\Redis类。我打开Illuminate\Support\Facades\Redis,一直追踪到其父类,最后卡在下面这个方法上protected static function resolveFacadeInstance($name)
{
if (is_object($name)) {
return $name;
}
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
return static::$resolvedInstance[$name] = static::$app[$name];
}最后一行,有个
static::$app[$name],当时就是不知道static::$app怎么给的值,现在终于找到了。。。我们看一下这行代码
Facade::setFacadeApplication($app);干了什么吧public static function setFacadeApplication($app)
{
static::$app = $app;
}看到了吧,
static::$app就是在这里赋的值。最后,有个小难点,也算是核心吧,就是注册类的别名
AliasLoader::getInstance(array_merge(
$app->make('config')->get('app.aliases', []),
$app->make(PackageManifest::class)->aliases()
))->register();这个就是调用
AliasLoader类的静态方法getInstance,以$app->make('config')->get('app.aliases', [])和$app->make(PackageManifest::class)->aliases()合并后的数组为参数,取返回值,这个返回值是对象,再调用这个对象的register方法。关于参数,
$app->make('config')->get('app.aliases', [])是有用的,取得就是app.php配置文件中的aliases数组;$app->make(PackageManifest::class)->aliases()返回的空数组,不用理会1、我们看一下
AliasLoader类的getInstance方法public static function getInstance(array $aliases = [])
{
if (is_null(static::$instance)) {
return static::$instance = new static($aliases);
}
$aliases = array_merge(static::$instance->getAliases(), $aliases);
static::$instance->setAliases($aliases);
return static::$instance;
}再来张截图,我们看一下参数
$aliases长什么样?
首先,是单例模式的经典判断,如果
static::$instance是null则实例化自身,否则跳过实例化自身,要调用 构造函数的,我们看看构造函数
private function __construct($aliases)
{
$this->aliases = $aliases;
}简单,就是一个
$aliases数组的赋值其次,由于第一次执行,
static::$instance一定为null,所以,直接return自身实例对象
2、我们看一下
AliasLoader类对象的register方法public function register()
{
if (! $this->registered) {
$this->prependToLoaderStack();
$this->registered = true;
}
}首先,判断是否注册过,由于第一次执行,所以未注册过,执行 if 里面的代码
其次,我们来看一下
$this->prependToLoaderStack();干了什么吧protected function prependToLoaderStack()
{
spl_autoload_register([$this, 'load'], true, true);
}看到没,类的自动加载方法又新增一个成员,他是
AliasLoader类对象的load方法。并优先执行,所以以后自动加载类,会先执行这里的load方法,然后执行 Composer 注册的自动加载方法也就是说,以后 Laravel 容器
make一个Redis会先加载Illuminate\Support\Facades\Redis::class类,不信,你看 app.php 配置文件 aliases 数组中键为Redis的值是什么吧。因此说,我们在使用
Illuminate\Support\Facades\RedisRedis 门面的时候可以简化 use ,如下<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Redis; // 这里就是简化
class UserController extends Controller
{
/**
* 显示给定用户的配置文件。
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
$user = Redis::get('user:profile:'.$id);
return view('user.profile', ['user' => $user]);
}
}